package server

import (
	"bytes"
	context2 "context"
	"dag2.0/gat1400-proxy/cache"
	"dag2.0/gat1400-proxy/context"
	"dag2.0/gat1400-proxy/db"
	"dag2.0/gat1400-proxy/logger"
	"dag2.0/gat1400-proxy/model"
	"dag2.0/gat1400-proxy/model/constant"
	"dag2.0/gat1400-proxy/util"
	"dag2.0/gat1400-proxy/util/times"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/json-iterator/go"
	uuid "github.com/satori/go.uuid"
	"math/rand"
	"net/http"
	"net/textproto"
	"strconv"
	//"net/textproto"
	"os"
	"strings"
	"sync"
	"time"
)

const (
	REC_ADDR             = "http://%s:%s/VIID/SubscribeNotifications"
	CANCELSUBSCRIBLE_URL = "http://%s:%s/VIID/Subscribes/%s"
)

func StartGat1400Server() {
	server := gin.Default()
	server.Handle(http.MethodGet, "/debug", changeLogLevel) //修改日志级别
	server.Handle(http.MethodGet, "/getManager", getManager)
	server.Handle(http.MethodGet, "/getSubscribe", getSubscribe)
	//视图库业务
	manager := server.Group("/api/dag/v2/gat1400/viewlib")
	manager.Handle(http.MethodPost, "/save", createManager)
	manager.Handle(http.MethodPost, "/find/:id", getManagerById)
	manager.Handle(http.MethodPost, "/findList", queryManagers)
	manager.Handle(http.MethodPost, "delete/:id", deleteManger)
	//订阅业务
	subscribe := server.Group("/api/dag/v2/gat1400/subscribe")
	subscribe.Handle(http.MethodPost, "/create", createSubscribe)
	subscribe.Handle(http.MethodPost, "/find/:id", getSubscribeById)
	subscribe.Handle(http.MethodPost, "/findsubcribe/:id", getSubscribeByManagerId)
	subscribe.Handle(http.MethodPost, "/findList", querySubscribes)
	subscribe.Handle(http.MethodPost, "update", updateSubscribe)
	subscribe.Handle(http.MethodPost, "/delete/:id", delSubscribeById)
	subscribe.Handle(http.MethodPost, "/repush", rePushSubscribe)
	//批量删除订阅
	subscribe.Handle(http.MethodPost, "/batchDeleteNotify", DeleteFormExcel)

	//管理业务
	manageRouter := server.Group("manage")
	//绑定视图库关联关系
	manageRouter.Handle(http.MethodPost, "/bindResource", bindResource)
	manageRouter.Handle(http.MethodPost, "/getResourceByID/:id", getResourceByID)
	manageRouter.Handle(http.MethodGet, "/debug", changeLogLevel) //修改日志级别
	manageRouter.Handle(http.MethodGet, "/getCache", getCache)    //获取内存中的缓存

	//1400server组件信息上报
	manageRouter.Handle(http.MethodPost, "/infoCollection", infoCollection)
	manageRouter.Handle(http.MethodGet, "/getApes", getViidApes) //获取指定视图库设备

	//1400协议业务
	viidRouter := server.Group("VIID")
	//设备获取
	viidRouter.Handle(http.MethodGet, "/APEs", getApes)
	//卡口获取
	viidRouter.Handle(http.MethodGet, "/Tollgates", getTollgates)
	//车道获取
	viidRouter.Handle(http.MethodGet, "/Lanes", getLane)
	//订阅
	viidRouter.Handle(http.MethodPost, "/Subscribes", subscribes)
	//viidRouter.Handle(http.MethodGet, "/Subscribes", getSubscribes) //查询
	viidRouter.Handle(http.MethodPut, "/Subscribes", subscribes)      //修改
	viidRouter.Handle(http.MethodDelete, "/Subscribes", unSubscribes) //删除
	//取消订阅
	viidRouter.Handle(http.MethodPost, "/Subscribes/:id", unSubscribes)
	viidRouter.Handle(http.MethodPut, "/Subscribes/:id", unSubscribes)
	//通知
	viidRouter.Handle(http.MethodPost, "/SubscribeNotifications", subscribeNotification)

	//重定向
	viidRouter.Handle(http.MethodPost, "/System/Register", register)
	//保活
	viidRouter.Handle(http.MethodPost, "/System/Keepalive", keepalive)
	//go server.Run(":14009")
	go server.Run(":" + context.GetString("port"))
}
func rePushSubscribe(ctx *gin.Context) {
	var err error
	sb := &model.SubscribeLib{}
	err = ctx.BindJSON(sb)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(err.Error(), ctx.Request.URL.String(), "", nil))
		return
	}
	//判断订阅任务
	details := strings.Split(sb.SubscribeDetail, ",")
	resourceFlag := false
	for _, detail := range details {
		switch detail {
		//资源
		case constant.EQUIPMENT_LIST, constant.EQUIPMENT_STATUS, constant.TOLLGATE_LIST,
			constant.SINGLE_TOLLGATE_INFO, constant.LAND_LIST, constant.SINGLE_LAND_INFO, constant.HIK_ILLEGAL:
			resourceFlag = true
		default:
			logger.LOG_WARN("不支持的订阅类型", detail)
		}
	}
	if resourceFlag {
		response, err := NotificationResource(sb, nil, false)
		if err != nil {
			ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, ctx.Request.URL.String(), "", response))
			return
		}
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, ctx.Request.URL.String(), "", nil))
}
func getManager(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, cache.GetIns().SubscribeManagers)
}
func getSubscribe(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, cache.GetIns().SubscribeTasks)
}

func keepalive(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.OK)))
}

func getCache(ctx *gin.Context) {
	logger.LOG_WARN(cache.GetIns().SubscribeTasks.Len())
	logger.LOG_WARN(cache.GetIns().SubscribeManagers.Len())
	logger.LOG_WARN(cache.GetIns().GatServerInfos.Len())
	cache.GetIns().GatServerInfos.Range(func(key string, value interface{}) bool {
		serverInfos := value.(*cache.GatServerInfoViewMap)
		serverInfos.Range(func(key string, value interface{}) bool {
			serInfo := value.(*model.GatServerInfo)
			serInfo.Weight = CalculateWeight(serInfo)
			return true
		})
		return true
	})
	ctx.JSON(http.StatusOK, cache.GetIns())
}

func register(ctx *gin.Context) {
	//获取视图库id
	var err error
	rm := &model.RegisterModel{}
	err = jsoniter.NewDecoder(ctx.Request.Body).Decode(rm)
	viewId := rm.GetViewID() //视图库id & 设备id
	if ctx.Request.Header.Get("User-Identify") != "" {
		viewId = ctx.Request.Header.Get("User-Identify")
	}
	if err != nil {
		ctx.JSON(http.StatusBadRequest, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, "", model.JSON_FORMAT_INVALID)))
		return
	}
	if viewId == "" {
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.VIEWID_IS_NULL)))
		return
	}
	//订阅的注册,直接返回200
	if _, ok := cache.GetIns().SubscribeManagers.Load(viewId); ok {
		//header params
		authorization := ctx.GetHeader("Authorization")
		logger.LOG_DEBUG("Authorization: ", authorization)
		if authorization == "" {
			//第一次注册
			nonce := strings.ReplaceAll(uuid.NewV4().String(), "-", "")[0:12]
			authorization = fmt.Sprintf(`Digest realm="myrealm",qop="auth",nonce="%s"`, nonce)
			mh := textproto.MIMEHeader(ctx.Writer.Header())
			mh["WWW-Authenticate"] = []string{authorization}
			ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.OK)))
			return
		}

		//第二次注册
		params := make(map[string]string)
		authorization = strings.Trim(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(authorization, "Digest", ""), "'", ""), `"`, ""), " ")
		logger.LOG_DEBUG("======Authorization=========: ", authorization)
		args := strings.Split(authorization, ",")
		for _, item := range args {
			//kv := strings.Split(item, "=")
			kv := strings.SplitN(item, "=", 2)
			if len(kv) == 2 {
				params[strings.Trim(kv[0], " ")] = strings.Trim(kv[1], " ")
			}
		}
		keys := []string{
			"username",
			"realm",
			"nonce",
			"cnonce",
			"response",
			//"algorithm",
			"qop",
			"nc"}
		for _, k := range keys {
			logger.LOG_DEBUG("k:  ", k, " param[k]: ", params[k])
			if params[k] == "" {
				logger.LOG_DEBUG(k + " is emtpy ")
				ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.INVALID_OPERATION)))
				return
			}
		}
		sm, err := db.QueryManagerById(viewId)
		if err != nil {
			logger.LOG_ERROR("查询视图库失败,  ", err)
			ctx.JSON(http.StatusInternalServerError, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.OTHER_ERROR)))
			return
		}
		logger.LOG_DEBUG("viewId:  ,sm.usernaem:  ,sm.password: ", viewId, sm.UserName, sm.Password)
		if sm == nil {
			ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.DEVICEID_IS_NOT_EXIST)))
			return
		}
		logger.LOG_DEBUG("sm.UserName: ", sm.UserName)
		logger.LOG_DEBUG("sm.password: ", sm.Password)
		logger.LOG_DEBUG("sm.UserName.length: ", len(sm.UserName))
		logger.LOG_DEBUG("sm.UserName.length.trime: ", len(strings.TrimSpace(sm.UserName)))
		if params["username"] == "" {
			ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.UAERNAEM_NOT_CORRECT)))
			return
		}
		//check auth
		//h1 := util.MD5(sm.UserName + ":" + params["realm"] + ":" + sm.Password)
		h1 := util.MD5(params["username"] + ":" + params["realm"] + ":" + strings.TrimSpace(sm.Password))
		logger.LOG_INFO("注册H1-params:", params["username"]+":"+params["realm"]+":"+sm.Password)
		logger.LOG_INFO("注册H1:", h1)
		h2 := util.MD5("POST:/VIID/System/Register")
		logger.LOG_INFO("注册H2-params:", "POST:/VIID/System/Register")
		logger.LOG_INFO("注册H2:", h2)
		res := util.MD5(h1 + ":" + params["nonce"] + ":" + params["nc"] + ":" + params["cnonce"] + ":" + params["qop"] + ":" + h2)
		logger.LOG_INFO("注册response-params:", h1+":"+params["nonce"]+":"+params["nc"]+":"+params["cnonce"]+":"+params["qop"]+":"+h2)
		logger.LOG_INFO("注册response:", res)
		logger.LOG_INFO("收到的response:", params["response"])
		if res != params["response"] {
			ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(model.URL_REGIST, viewId, model.RESPONSE_NOT_CORRECT)))
			return
		}

		//logger.LOG_WARN("注册成功")
		// 注册成功
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.OK)))
		return
	}

	//重定向逻辑
	//1.遍历所有上报信息，找到设备国标与视图库id的映射关系
	managerMaps := make(map[string]string, 0)
	cache.GetIns().GatServerInfos.Range(func(managerKey string, value interface{}) bool {
		//视图库id
		managerMaps[managerKey] = managerKey
		//视图库id为多个,并且以“，”分割的时候
		managerKeys := strings.Split(strings.Trim(managerKey, " "), ",")
		for _, value := range managerKeys {
			managerMaps[value] = managerKey
		}
		serverInfos := value.(*cache.GatServerInfoViewMap)
		serverInfos.Range(func(key string, value interface{}) bool {
			serInfo := value.(*model.GatServerInfo)
			for _, id := range serInfo.ResourceGbIds {
				//设备国标id
				managerMaps[id] = managerKey
			}
			return true
		})
		return true
	})
	//2.未找到找到下级注册对应的视图库id
	v, ok := managerMaps[viewId]
	if !ok {
		logger.LOG_ERROR("未含有此视图库id的服务列表  ", viewId)
		ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.DEVICEID_IS_NOT_EXIST)))
		return
	}
	//3.通过视图库id获取需要重定向的节点
	serverInfosInter, ok := cache.GetIns().GatServerInfos.Load(v)
	if !ok {
		logger.LOG_ERROR("未含有此视图库id的服务列表信息   ", viewId+" : "+v)
		ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.DEVICEID_IS_NOT_EXIST)))
		return
	}
	serverInfos := serverInfosInter.(*cache.GatServerInfoViewMap)
	if serverInfos.Len() == 0 {
		logger.LOG_ERROR("此视图库id的服务列表信息为空")
		ctx.JSON(http.StatusUnauthorized, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.DEVICEID_IS_NOT_EXIST)))
		return
	}
	findSerInfo := FindSerInfo(serverInfos)
	findSerInfo.AllocateTime = time.Now().UnixNano() / 1e6
	findSerInfo.AllocateNum += 1
	ctx.Header("Location", "http://"+findSerInfo.ServerAddr+"/VIID/System/Register")
	//mh := textproto.MIMEHeader(ctx.Writer.Header())
	//mh["Location"] = []string{}
	logger.LOG_WARN("【重定向】 ", ctx.Request.Host, "  ====>  ", findSerInfo.ServerAddr)
	ctx.JSON(http.StatusFound, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.OK)))
}

func build1400ServerResponse(code int, Data []byte, Success bool, Message string) *util.ResponseWrap {
	return &util.ResponseWrap{
		Code:    code,
		Data:    Data,
		Success: Success,
		Message: Message,
	}
}
func infoCollection(ctx *gin.Context) {
	var err error
	si := &model.GatServerInfo{}
	buff := bytes.NewBuffer(make([]byte, 0))
	_, err = buff.ReadFrom(ctx.Request.Body)
	if err != nil {
		logger.LOG_ERROR("1400server信息上报 读取数据流失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_FORMAT_INVALID)))
		return
	}
	if logger.IsDebug() {
		logger.LOG_DEBUG("上报状态为:", string(buff.Bytes()))
	}
	err = jsoniter.Unmarshal(buff.Bytes(), si)
	if err != nil {
		logger.LOG_ERROR("解析失败", err)
		ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
	}
	gatServerInfoMapInterface := cache.GetIns().GatServerInfos.LoadOrStore(si.ServerViewId)
	if _, ok := gatServerInfoMapInterface.(*cache.GatServerInfoViewMap); !ok {
		logger.LOG_ERROR(fmt.Sprintf("类型错误,需要【*model.gatServerInfoViewMaps】类型，类型为%T", gatServerInfoMapInterface))
		ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
	}
	gatServerInfoMap := gatServerInfoMapInterface.(*cache.GatServerInfoViewMap)
	if gatServerInfoInter, ok := gatServerInfoMap.Load(si.ServerId); ok {
		gatServerInfo := gatServerInfoInter.(*model.GatServerInfo)
		si.AllocateNum = gatServerInfo.AllocateNum
		si.AllocateTime = gatServerInfo.AllocateTime
	}
	gatServerInfoMap.Store(si.ServerId, si)
	ctx.JSON(http.StatusOK, build1400ServerResponse(http.StatusOK, nil, true, ""))
}

var lock sync.Mutex

func changeLogLevel(ctx *gin.Context) {
	level := ctx.Query("level")
	if level != "" {
		logger.ChangeLevel(level)
	}
}
func getTollgates(ctx *gin.Context) {
	//获取视图库id
	if ctx.Request.Header.Get("User-Identify") == "" {
		logger.LOG_ERROR("请求中未含有视图库id")
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.VIEWID_IS_NULL)))
		return
	}
	subscribeManagerInterFace, _ := cache.GetIns().SubscribeManagers.Load(ctx.Request.Header.Get("User-Identify"))
	subscribeManager := subscribeManagerInterFace.(*model.SubscribeManagerEx)
	var tollgateObj = make([]*model.Tollgate, 0)
	if subscribeManager.TollgateIds != nil && len(subscribeManager.TollgateIds) > 0 {
		urmTollgate, err := Dealtollgate(subscribeManager.TollgateIds)
		if err != nil {
			logger.LOG_ERROR("获取urm卡口失败")
			ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
			return
		}
		//卡口
		tollgateObj = model.BuildTollgate(urmTollgate)
	}
	if len(tollgateObj) == 0 {
		logger.LOG_WARN("未绑定卡口")
		//ctx.JSON(http.StatusOK, nil)
		//return
	}
	TollgateListObjectEntity := &model.TollgateListObjectEntity{TollgateObject: tollgateObj}
	TollgateListObject := &model.TollgateListObject{TollgateListObject: TollgateListObjectEntity}
	ctx.JSON(http.StatusOK, TollgateListObject)
}
func getLane(ctx *gin.Context) {
	//获取视图库id
	if ctx.Request.Header.Get("User-Identify") == "" {
		logger.LOG_ERROR("请求中未含有视图库id")
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.VIEWID_IS_NULL)))
		return
	}
	subscribeManagerInterFace, _ := cache.GetIns().SubscribeManagers.Load(ctx.Request.Header.Get("User-Identify"))
	subscribeManager := subscribeManagerInterFace.(*model.SubscribeManagerEx)
	var laneObj = make([]*model.Lane, 0)
	if subscribeManager.TollgateIds != nil && len(subscribeManager.TollgateIds) > 0 {
		urmTollgate, err := Dealtollgate(subscribeManager.TollgateIds)
		if err != nil {
			logger.LOG_ERROR("获取urm卡口失败")
			ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
			return
		}
		//卡口
		laneObj = model.BuildLaneByTg(urmTollgate)
	}
	if len(laneObj) == 0 {
		ctx.JSON(http.StatusOK, nil)
		return
	}
	LaneListObjectEntity := &model.LaneListObjectEntity{LaneObject: laneObj}
	LaneListObject := &model.LaneListObject{LaneListObject: LaneListObjectEntity}
	ctx.JSON(http.StatusOK, LaneListObject)
}

func getViidApes(ctx *gin.Context) {
	viewId := ctx.DefaultQuery("viewId", "1")
	subscribeManagerInterFace, isExit := cache.GetIns().SubscribeManagers.Load(viewId)
	if !isExit {
		logger.LOG_ERROR("未找到视图库id为viewId的视图库信息")
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.VIEWID_IS_NULL)))
	}
	subscribeManager := subscribeManagerInterFace.(*model.SubscribeManagerEx)
	param := "?RecordStartNo=1&PageRecordNum=10000"
	bytes, _, resCode, err := util.Request(subscribeManager.ManagerIp+":"+subscribeManager.ManagerPort+constant.URL_APE+param, http.MethodGet, map[string]string{
		"Content-Type":  "application/VIID+JSON",
		"User-Identify": subscribeManager.SelfManagerID,
	}, nil, nil)
	if err != nil || (resCode != http.StatusOK && resCode != http.StatusCreated && resCode != http.StatusNoContent) {
		logger.LOG_ERROR("获取设备失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_APE, "获取设备请求失败", model.OTHER_ERROR)))
	}

	if bytes != nil && len(bytes) > 0 {
		apeObject := &model.APEListObject{}
		err := jsoniter.Unmarshal(bytes, apeObject)
		if nil == err && apeObject.APEListObject != nil && len(apeObject.APEListObject.APEObject) > 0 {
			apes := apeObject.APEListObject.APEObject
			var urmDevices = make([]*model.URMEquipment, 0) //采集设备
			logger.LOG_WARN("通知结构为:", util.BytesString(bytes))
			//采集设备处理
			urmDevices = append(urmDevices, transformApes(apes, viewId)...)
			if len(urmDevices) > 0 {
				//调用urm接口保存采集设备
				bytes, _, _, e := util.Request(fmt.Sprintf(URM_ADD_EQUIPMENT, os.Getenv("URM_IP_PORT")), http.MethodPost, map[string]string{
					"Content-Type": "application/json",
				}, urmDevices, nil)
				if e != nil {
					logger.LOG_ERROR("保存采集设备至urm失败", e)
					return
				}
				if _, e := analyzeUrmRsponse(bytes); e != nil {
					logger.LOG_ERROR("保存采集设备至urm失败", e)
					return
				}
				logger.LOG_WARN("保存采集设备至urm成功,采集设备个数为 ：", len(urmDevices))
			}
		}
	}

}

func getApes(ctx *gin.Context) {
	//获取视图库id
	if ctx.Request.Header.Get("User-Identify") == "" {
		logger.LOG_ERROR("请求中未含有视图库id")
		ctx.JSON(http.StatusOK, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.Path, "", model.VIEWID_IS_NULL)))
		return
	}
	recordStartNo, _ := strconv.Atoi(ctx.DefaultQuery("RecordStartNo", "1"))
	pageRecordNum, _ := strconv.Atoi(ctx.DefaultQuery("PageRecordNum", "50000"))

	subscribeManagerInterFace, _ := cache.GetIns().SubscribeManagers.Load(ctx.Request.Header.Get("User-Identify"))
	subscribeManager := subscribeManagerInterFace.(*model.SubscribeManagerEx)

	var apeObject = make([]*model.APE, 0)

	if subscribeManager.EquipmentIds != nil && len(subscribeManager.EquipmentIds) > 0 {
		urmEquipments := make([]*model.URMEquipment, 0)
		var getResourceErr error
		//获取urm采集设备
		// 判断是否分页查询，公安部需求
		recordStartNo := ctx.Query("RecordStartNo")
		pageRecordNum := ctx.Query("PageRecordNum")
		logger.LOG_DEBUG("recordStartNo: ", recordStartNo, " pageRecordNum: ", pageRecordNum)
		if len(strings.TrimSpace(recordStartNo)) == 0 || len(strings.TrimSpace(pageRecordNum)) == 0 {
			urmEquipments, getResourceErr = DealEquipment(subscribeManager.EquipmentIds)
		} else {
			// 分页查询
			_start, _ := strconv.Atoi(recordStartNo)
			_pageRecordNum, _ := strconv.Atoi(pageRecordNum)
			urmEquipments, getResourceErr = DealEquipmentPageList(subscribeManager.EquipmentIds, _start, _pageRecordNum)
		}

		if getResourceErr != nil {
			logger.LOG_ERROR("获取设备资源信息失败", getResourceErr)
			ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
			return
		}
		//采集设备
		if urmEquipments != nil && len(urmEquipments) > 0 {
			apeObject = append(apeObject, model.BuildAPEFromUrmEquipments(urmEquipments)...)
		}
	}
	if subscribeManager.TollgateIds != nil && len(subscribeManager.TollgateIds) > 0 {
		urmTollgates := make([]*model.URMTollgate, 0)
		var getTollResourceErr error
		//获取urm卡口
		urmTollgates, getTollResourceErr = Dealtollgate(subscribeManager.TollgateIds)
		if getTollResourceErr != nil {
			logger.LOG_ERROR("获取卡口资源信息失败", getTollResourceErr)
			ctx.JSON(http.StatusInternalServerError, build1400ServerResponse(http.StatusInternalServerError, nil, false, ""))
			return
		}
		if urmTollgates != nil && len(urmTollgates) > 0 {
			apeObject = append(apeObject, model.BuildAPEFromUrmTollgate(urmTollgates)...)
		}
	}
	start := (recordStartNo - 1) * pageRecordNum
	end := len(apeObject)
	if end < start {
		//apeListObjectEntity := &model.APEListObjectEntity{APEObject: apeObject}
		ApeListObject := &model.APEListObject{}
		ctx.JSON(http.StatusOK, ApeListObject)
		return
	}
	if pageRecordNum*recordStartNo < end {
		end = pageRecordNum * recordStartNo
	}
	apes := apeObject[start:end]
	apeListObjectEntity := &model.APEListObjectEntity{APEObject: apes}
	ApeListObject := &model.APEListObject{APEListObject: apeListObjectEntity}
	ctx.JSON(http.StatusOK, ApeListObject)
}

func subscribeNotification(ctx *gin.Context) {
	if ctx.Request.Header.Get("User-Identify") == "" {
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.VIEWID_IS_NULL)))
		logger.LOG_ERROR("订阅头中未含有视图库id")
		return
	}
	viewId := ctx.Request.Header.Get("User-Identify")
	var err error
	ar := &model.SubscribeNotificationModel{}
	buff := bytes.NewBuffer(make([]byte, 0))
	_, err = buff.ReadFrom(ctx.Request.Body)
	if err != nil {
		logger.LOG_ERROR("通知结构体 读取数据流失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_FORMAT_INVALID)))
		return
	}
	err = jsoniter.Unmarshal(buff.Bytes(), ar)
	if err != nil {
		logger.LOG_ERROR("通知结构体 解析json失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_FORMAT_INVALID)))
		return
	}
	if ar.SubscribeNotificationListObject == nil || len(ar.SubscribeNotificationListObject.SubscribeNotificationObject) < 0 {
		logger.LOG_ERROR("通知结构体不合法")
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_CONTENT_INVALID)))
		return
	}
	//判断此视图库是是否以备案
	if _, ok := cache.GetIns().SubscribeManagers.Load(viewId); !ok {
		logger.LOG_ERROR("通知信息中，视图库编号未备案")
		ctx.JSON(http.StatusUnauthorized, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.UNAUTHORIZED)))
		return
	}
	e := DealResourceNotification(ar, viewId)
	if e != nil {
		ctx.JSON(http.StatusInternalServerError, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.OTHER_ERROR)))
		return
	}
	ctx.JSON(http.StatusOK, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.OK)))
}

// 创建订阅
func createSubscribe(ctx *gin.Context) {
	var err error
	sb := &model.SubscribeLib{}
	buff := bytes.NewBuffer(make([]byte, 0))
	_, err = buff.ReadFrom(ctx.Request.Body)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_CREATESUBSCRIBES, "", nil))
		return
	}
	err = jsoniter.Unmarshal(buff.Bytes(), sb)
	//err = ctx.BindJSON(sb)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_CREATESUBSCRIBES, "", nil))
		return
	}
	if sb.ReceiveAddr == "" {
		sb.ReceiveAddr = fmt.Sprintf(REC_ADDR, os.Getenv("DOCKER_HOST_IP"), "14000")
	}
	sb.SubscribeID = generateSubscribeID()
	sb.InsertTime = times.Time2Str()
	sb.UpdateTime = times.Time2Str()
	err = db.InsertSubscribe(sb)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_CREATESUBSCRIBES, "", nil))
		return
	}
	//更新缓存
	cache.GetIns().SubscribeTasks.Store(sb.SubscribeID, sb)
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_CREATESUBSCRIBES, "", nil))
}

// 查询：id订阅信息
func getSubscribeById(ctx *gin.Context) {
	id := ctx.Param("id")
	sb, err := db.QuerySubscribeById(id)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.RESULT_IS_NULL, constant.URL_GETSUBSCRIBEBYID, id, nil))
		return
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_GETSUBSCRIBEBYID, id, sb))
}

// 根據視圖庫id查詢訂閱信息表
func getSubscribeByManagerId(ctx *gin.Context) {
	id := ctx.Param("id")
	sb, err := db.QuerySubscribeByManagerId(id)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.RESULT_IS_NULL, constant.URL_GETSUBSCRIBEBYMANAGERID, id, nil))
		return
	}
	var sbs = make([]*model.SubscribeLib, 0)
	for _, s := range sb {
		if s.OperateType != -1 {
			sbs = append(sbs, s)
		}
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_GETSUBSCRIBEBYMANAGERID, id, sbs))
}

// 获取所有订阅信息
func querySubscribes(ctx *gin.Context) {
	sbs, err := db.QuerySubscribes()
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_QUERYSUBSCRIBES, "", nil))
		return
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_QUERYSUBSCRIBES, "", sbs))
}

// 更新:id订阅
func updateSubscribe(ctx *gin.Context) {
	var err error
	sb := &model.SubscribeLib{}
	err = ctx.BindJSON(sb)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_UPDATESUBSCRIBEBYID, "", nil))
		return
	}
	sb.UpdateTime = times.Time2Str()
	err = db.UpdateSubscribe(sb)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_UPDATESUBSCRIBEBYID, "", nil))
		return
	}
	//更新缓存
	cache.GetIns().SubscribeTasks.Store(sb.SubscribeID, sb)
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_UPDATESUBSCRIBEBYID, "", nil))
}

// 删除:id订阅
func delSubscribeById(ctx *gin.Context) {
	id := ctx.Param("id")
	if id == "" {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.SUBCRIBEID_IS_NULL, constant.URL_DELSUBSCRIBEBYID, id, nil))
		return
	}
	subscribeTaskInter, ok := cache.GetIns().SubscribeTasks.Load(id)
	if !ok {
		logger.LOG_ERROR("为含有此订阅id的订阅信息  :", id)
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_DELSUBSCRIBEBYID, id, nil))
		return
	}
	//更改数据库状态
	subscribelib := subscribeTaskInter.(*model.SubscribeLib)
	//判断是否为上级的订阅,上级的订阅状态是取消的直接删除
	if m, ok := cache.GetIns().SubscribeManagers.Load(subscribelib.ManagerID); ok {
		manager := m.(*model.SubscribeManagerEx)
		if manager.ManagerType == constant.MANAGER_UP {
			if subscribelib.OperateType != 1 && subscribelib.OperateType != -1 {
				ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_DELSUBSCRIBEBYID, id, nil))
				return
			}
			e := db.DeleteSubcribeById(subscribelib.SubscribeID)
			if e != nil {
				logger.LOG_ERROR("删除订阅失败", e)
				ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_DELSUBSCRIBEBYID, id, nil))
				return
			}
			//删除缓存中的订阅任务
			cache.GetIns().SubscribeTasks.Delete(subscribelib.SubscribeID)
			ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_DELSUBSCRIBEBYID, id, nil))
			return
		}
	}
	err := db.UpdateOperateTypeBySubscribeID(subscribelib.SubscribeID, "-1", strconv.Itoa(int(subscribelib.SubscribeStatus)))
	if err != nil {
		logger.LOG_ERROR("更新订阅失败 ", err)
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_DELSUBSCRIBEBYID, id, nil))
		return
	}
	//更改内存
	subscribelib.OperateType = -1
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_DELSUBSCRIBEBYID, id, nil))

}

// 视图库创建与修改
func createManager(ctx *gin.Context) {
	var err error
	sm := &model.SubscribeManager{}
	err = ctx.BindJSON(sm)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_CREATESUBSCRIBES, "", nil))
		return
	}
	//更新视图库
	if managerInterFace, ok := cache.GetIns().SubscribeManagers.Load(sm.ManagerID); ok {
		e := db.UpdateManager(sm)
		if e != nil {
			ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_CREATESUBSCRIBES, "", nil))
			return
		}
		//更新缓存
		manager := managerInterFace.(*model.SubscribeManagerEx)
		manager.SubscribeManager = sm
	} else {
		//新增视图库
		sm.InsertTime = times.Time2Str()
		sm.UpdateTime = times.Time2Str()
		e := db.InsertManager(sm)
		if e != nil {
			ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_CREATESUBSCRIBES, "", nil))
			return
		}
		ctx, cancel := context2.WithCancel(context2.Background())
		//更新缓存
		cache.GetIns().SubscribeManagers.Store(sm.ManagerID, &model.SubscribeManagerEx{
			SubscribeManager: sm,
			EquipmentIds:     make([]string, 0),
			TollgateIds:      make([]string, 0),
			TaskIds:          make([]string, 0),
			IsRegister:       false,
			RegisterSuccess:  false,
			ExecuteOperation: 0,
			Ctx:              ctx,
			Cancel:           cancel,
		})
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_CREATESUBSCRIBES, sm.ManagerID, nil))
}

// 获取：id视图库
func getManagerById(ctx *gin.Context) {
	id := ctx.Param("id")
	sm, err := db.QueryManagerById(id)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.RESULT_IS_NULL, constant.URL_GETMANAGERBYID, id, nil))
		return
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_GETMANAGERBYID, id, sm))
}

// 获取所有视图库信息
func queryManagers(ctx *gin.Context) {
	sms, err := db.QueryAllManager()
	if err != nil {
		logger.LOG_ERROR("获取视图库失败", err)
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_GQUERYMANAGERS, "", nil))
		return
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_GQUERYMANAGERS, "", sms))
}

// 删除：id视图库
func deleteManger(ctx *gin.Context) {
	id := ctx.Param("id")
	if id == "" {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.PARAM_IS_EMPTY, constant.URL_DELETEMANGER, id, nil))
		return
	}
	e := db.DeleteSubcribeManagerById(id)
	if e != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_DELETEMANGER, id, nil))
		return
	}
	//删除视图库之后，删除内存中的订阅任务
	var delSubscribeIds = make([]string, 0)
	cache.GetIns().SubscribeTasks.Range(func(key string, value interface{}) (shouldContinue bool) {
		subscribeLib := value.(*model.SubscribeLib)
		if subscribeLib.ManagerID == id {
			delSubscribeIds = append(delSubscribeIds, subscribeLib.SubscribeID)
		}
		return true
	})
	//删除视图库

	cache.GetIns().SubscribeManagers.Delete(id)
	for _, delSubscribeId := range delSubscribeIds {
		logger.LOG_WARN("删除视图库，并删除订阅任务 ,订阅id为: ", delSubscribeId)
		cache.GetIns().SubscribeTasks.Delete(delSubscribeId)
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_DELETEMANGER, id, nil))
}

// 绑定视图库资源关系
func bindResource(ctx *gin.Context) {
	var err error
	view := &model.ViewInfo{}
	err = ctx.BindJSON(view)
	if err != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.JSON_FORMAT_INVALID, constant.URL_BINDRESOURCE, "", nil))
		return
	}
	addRes, deleteRes, taskRes := createViewLibs(view)
	err = db.UpdateResource(addRes, deleteRes, taskRes)
	if err != nil {
		logger.LOG_ERROR("执行错误", err)
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_BINDRESOURCE, "", nil))
		return
	}
	//修改订阅任务的订阅状态
	cache.GetIns().SubscribeTasks.Range(func(key string, value interface{}) (shouldContinue bool) {
		if _, ok := value.(*model.SubscribeLib); !ok {
			logger.LOG_ERROR(fmt.Sprintf("类型转换错误，需要*model.SubscribeLib 类型，类型为:%T", value))
			return true
		}
		subscribeLib := value.(*model.SubscribeLib)
		if subscribeLib.ManagerID == view.ManagerID && subscribeLib.OperateType != 1 && subscribeLib.SubscribeStatus == 99 {
			logger.LOG_WARN("更新订阅任务状态")
			_ = FlushSubscribeStatusCache(subscribeLib, "0", "")
		}
		return true
	})
	//更新缓存
	viewInfo, err := db.QueryByViewId(view.ManagerID)
	if err != nil {
		logger.LOG_ERROR("获取已绑定资源失败  ", err)
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_BINDRESOURCE, "", nil))
		return
	}
	if managerInter, ok := cache.GetIns().SubscribeManagers.Load(view.ManagerID); ok {
		manager := managerInter.(*model.SubscribeManagerEx)
		manager.TaskIds = viewInfo.TaskIds
		manager.EquipmentIds = viewInfo.EquipmentIds
		manager.TollgateIds = viewInfo.TollgateIds
	} else {
		logger.LOG_ERROR("未找到此视图库，请检查代码逻辑")
	}
	//删除资源通知
	//go deleteResourceNotify(view)
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_BINDRESOURCE, "", nil))
}
func deleteResourceNotify(view *model.ViewInfo) {
	var addEqIds = make(map[string]bool)
	var addTgIds = make(map[string]bool)
	var updEqIds = make(map[string]bool)
	var updTgIds = make(map[string]bool)
	var delEqIds = make(map[string]bool)
	var delTgIds = make(map[string]bool)

	if "" != view.IncEquipmentIds {
		for _, t := range strings.Split(view.IncEquipmentIds, ",") {
			addEqIds[t] = true
		}
	}
	if "" != view.IncTollgateIds {
		for _, t := range strings.Split(view.IncTollgateIds, ",") {
			addTgIds[t] = true
		}
	}
	if "" != view.DecEquipmentIds {
		for _, t := range strings.Split(view.DecEquipmentIds, ",") {
			delEqIds[t] = true
		}
	}
	if "" != view.DecTollgateIds {
		for _, t := range strings.Split(view.DecTollgateIds, ",") {
			delTgIds[t] = true
		}
	}

	bindResources, err := db.QueryByViewId(view.ManagerID)
	if err != nil {
		logger.LOG_ERROR("查询绑定资源异常：", err.Error())
		return
	}
	//已绑定资源，排除本次新增和删除资源，即为更新资源
	if len(bindResources.EquipmentIds) != 0 {
		for _, equipmentId := range bindResources.EquipmentIds {
			if addEqIds[equipmentId] && delEqIds[equipmentId] {
				continue
			}
			updEqIds[equipmentId] = true
		}
	}
	if len(bindResources.TollgateIds) != 0 {
		for _, tollgateId := range bindResources.TollgateIds {
			if addTgIds[tollgateId] && delTgIds[tollgateId] {
				continue
			}
			updTgIds[tollgateId] = true
		}
	}
	logger.LOG_WARN("deleteResourceNotify", " updEqIdsSize= ", len(updEqIds), ", updTgIdsSize= ", len(updTgIds), ", delEqIdsSize= ", len(delEqIds), ", delTgIdsSize= ", len(delTgIds))
	logger.LOG_DEBUG("deleteResourceNotify", " updEqIds=", updEqIds, ", updTgIds=", updTgIds, ", delEqIds=", delEqIds, ", delTgIds=", delTgIds)
	watchNotify(updEqIds, updTgIds, delEqIds, delTgIds)
}

func getResourceByID(ctx *gin.Context) {
	id := ctx.Param("id")
	vo, e := db.QueryByViewId(id)
	if e != nil {
		ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OTHER_ERROR, constant.URL_GETRESOURCEBYID, id, nil))
		return
	}
	if vo == nil {
		vo = &model.ViewInfoVo{
			ManagerID:    "",
			EquipmentIds: make([]string, 0),
			TollgateIds:  make([]string, 0),
			TaskIds:      make([]string, 0),
		}
	}
	ctx.JSON(http.StatusOK, model.BuildResourceResponse(model.OK, constant.URL_GETRESOURCEBYID, id, vo))
}

func createViewLibs(view *model.ViewInfo) (addRes, deleteRes, taskRes []*model.ViewLib) {
	addRes = make([]*model.ViewLib, 0)
	deleteRes = make([]*model.ViewLib, 0)
	taskRes = make([]*model.ViewLib, 0)
	//绑定的任务修改
	if len(view.TaskIds) > 0 {
		for _, t := range strings.Split(view.TaskIds, ",") {
			taskRes = append(taskRes, &model.ViewLib{
				MangerID:   view.ManagerID,
				Type_:      constant.TYPE_TASK,
				ResourceID: t,
			})
		}
	}
	if len(view.IncEquipmentIds) > 0 {
		for _, t := range strings.Split(view.IncEquipmentIds, ",") {
			addRes = append(addRes, &model.ViewLib{
				MangerID:   view.ManagerID,
				Type_:      constant.TYPE_EQUIPMENT,
				ResourceID: t,
			})
		}
	}
	if len(view.IncTollgateIds) > 0 {
		for _, t := range strings.Split(view.IncTollgateIds, ",") {
			addRes = append(addRes, &model.ViewLib{
				MangerID:   view.ManagerID,
				Type_:      constant.TYPE_TOLLGATE,
				ResourceID: t,
			})
		}
	}
	if len(view.DecEquipmentIds) > 0 {
		for _, t := range strings.Split(view.DecEquipmentIds, ",") {
			deleteRes = append(deleteRes, &model.ViewLib{
				MangerID:   view.ManagerID,
				ResourceID: t,
				Type_:      constant.TYPE_EQUIPMENT,
			})
		}
	}
	if len(view.DecTollgateIds) > 0 {
		for _, t := range strings.Split(view.DecTollgateIds, ",") {
			deleteRes = append(deleteRes, &model.ViewLib{
				MangerID:   view.ManagerID,
				ResourceID: t,
				Type_:      constant.TYPE_TOLLGATE,
			})
		}
	}
	return
}

// 订阅
func subscribes(ctx *gin.Context) {
	if ctx.Request.Header.Get("User-Identify") == "" {
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.VIEWID_IS_NULL)))
		logger.LOG_ERROR("订阅头中未含有视图库id")
		return
	}
	viewId := ctx.Request.Header.Get("User-Identify")
	var err error
	ar := &model.SubscribeModel{}
	buff := bytes.NewBuffer(make([]byte, 0))
	n := int64(0)
	n, err = buff.ReadFrom(ctx.Request.Body)
	logger.LOG_DEBUG("body size is :", n)
	if err != nil {
		logger.LOG_ERROR("订阅结构体 读取数据流失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_FORMAT_INVALID)))
		return
	}
	err = jsoniter.Unmarshal(buff.Bytes(), ar)
	if err != nil {
		logger.LOG_ERROR("订阅结构体 解析json失败", err)
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_FORMAT_INVALID)))
		return
	}
	if ar.SubscribeListObject == nil || len(ar.SubscribeListObject.SubscribeObject) < 0 {
		logger.LOG_ERROR("订阅结构体不合法")
		ctx.JSON(http.StatusBadRequest, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.JSON_CONTENT_INVALID)))
		return
	}
	jsonData, _ := jsoniter.Marshal(ar)
	logger.LOG_WARN("订阅请求为： ", util.BytesString(jsonData))
	if _, ok := cache.GetIns().SubscribeManagers.Load(viewId); !ok {
		logger.LOG_ERROR("订阅信息中，视图库编号未备案")
		ctx.JSON(http.StatusUnauthorized, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.UNAUTHORIZED)))
		return
	}

	res := &model.ResponseStatusListObject{}
	for _, subscribe := range ar.SubscribeListObject.SubscribeObject {
		err = DealSubscribe(subscribe, viewId)
		res.ResponseStatusObject = append(res.ResponseStatusObject, &model.ResponseStatusObject{
			ID:           subscribe.SubscribeID,
			LocalTime:    times.Time2StrF(time.Now(), "20060102150405"),
			RequestURL:   constant.URL_SUBSCRIBES,
			StatusCode:   model.OK,
			StatusString: "正常",
		})
	}
	if err != nil {
		logger.LOG_ERROR("订阅任务处理错误", err)
		ctx.JSON(http.StatusInternalServerError, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.OTHER_ERROR)))
		return
	}
	//ctx.JSON(http.StatusOK, model.BuildResponse(model.BuildRespnseObject(constant.URL_SUBSCRIBES, "", model.OK)))
	logger.LOG_DEBUG("订阅返回的结构体内层", res)
	ctx.JSON(http.StatusOK, model.BuildResponseList(res))
}

func DealSubscribe(subscribe *model.Subscribe, viewId string) error {
	unExsitKeys := IsExitConfi(subscribe.SubscribeDetail, subscribe.ReceiveAddr)
	if len(unExsitKeys) > 0 {
		logger.LOG_ERROR("订阅信息中，未含有相关配置", strings.Join(unExsitKeys, ","))
		return errors.New(fmt.Sprintf("订阅信息中，未含有 %s 配置", strings.Join(unExsitKeys, ",")))
	}
	subscribeManagerInterface, _ := cache.GetIns().SubscribeManagers.Load(viewId)
	if _, ok := subscribeManagerInterface.(*model.SubscribeManagerEx); !ok {
		logger.LOG_ERROR(fmt.Sprintf("类型转换错误，需要*model.SubscribeManagerEx 类型，类型为:%T", subscribeManagerInterface))
		return errors.New(fmt.Sprintf("类型转换错误，需要*model.SubscribeManagerEx 类型，类型为:%T", subscribeManagerInterface))
	}
	//已存在的订阅，修改
	if s, ok := cache.GetIns().SubscribeTasks.Load(subscribe.SubscribeID); ok {
		subscribeLibCache := s.(*model.SubscribeLib)
		//改库
		subscribeLib := &model.SubscribeLib{
			Subscribe:   subscribe,
			ManagerID:   viewId,
			ManagerName: subscribeLibCache.ManagerName,
			UpdateTime:  times.Time2Str(),
			InsertTime:  times.Time2Str(),
		}
		err := db.UpdateSubscribeBySubscribeID(subscribe.SubscribeID, subscribeLib)
		if err != nil {
			logger.LOG_ERROR("订阅修改失败")
			return errors.New("订阅修改失败")
		}
		cache.GetIns().SubscribeTasks.Store(subscribeLib.Subscribe.SubscribeID, subscribeLib)
		//subscribeLib.Subscribe = subscribe
	} else {
		subscribeManager := subscribeManagerInterface.(*model.SubscribeManagerEx)
		//构造入库参数
		subscribeLib := &model.SubscribeLib{
			Subscribe:   subscribe,
			ManagerID:   viewId,
			ManagerName: subscribeManager.ManagerName,
			UpdateTime:  times.Time2Str(),
			InsertTime:  times.Time2Str(),
		}
		//入订阅库
		err := db.InsertSubscribe(subscribeLib)
		if err != nil {
			logger.LOG_ERROR("订阅入库失败")
			return errors.New("入库失败")
		}
		//刷新任务缓存
		cache.GetIns().SubscribeTasks.Store(subscribeLib.Subscribe.SubscribeID, subscribeLib)
	}
	return nil
}

// 取消订阅
func unSubscribes(ctx *gin.Context) {
	subscribeId := ctx.Param("id")
	subscribeIds := ctx.Query("IDList")
	if subscribeId == "" && subscribeIds == "" {
		logger.LOG_ERROR("取消订阅id为空")
		ctx.JSON(http.StatusBadRequest, model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.String(), "", model.SUBCRIBEID_IS_NULL)))
		return
	}
	logger.LOG_DEBUG("取消订阅", subscribeId, subscribeIds)

	// 取消订阅或者修改订阅
	if subscribeId != "" {
		ctx.JSON(http.StatusOK, cancelSubscribe(subscribeId, ctx))
		return
	}
	// 删除订阅
	if len(subscribeIds) > 0 {
		ids := strings.Split(strings.TrimSpace(subscribeIds), ",")
		responses := make([]*model.ResponseStatusObject, 0)
		for _, id := range ids {
			response := cancelSubscribe(id, ctx)
			obj := &model.ResponseStatusObject{
				ID:           response.ResponseStatusObject.ID,
				LocalTime:    response.ResponseStatusObject.LocalTime,
				RequestURL:   response.ResponseStatusObject.RequestURL,
				StatusCode:   response.ResponseStatusObject.StatusCode,
				StatusString: response.ResponseStatusObject.StatusString,
			}
			responses = append(responses, obj)
		}
		ctx.JSON(http.StatusOK, model.BuildResponse(responses...))
	}
}

func cancelSubscribe(subscribeId string, ctx *gin.Context) *model.ResponseStatusSingleObj {
	//未包含此订阅任务，直接返回成功
	if _, ok := cache.GetIns().SubscribeTasks.Load(subscribeId); !ok {
		logger.LOG_ERROR("未包含此id的订阅任务")
		return model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.String(), subscribeId, model.OK))
	}
	subscribeTaskInterface, _ := cache.GetIns().SubscribeTasks.Load(subscribeId)
	if _, ok := subscribeTaskInterface.(*model.SubscribeLib); !ok {
		logger.LOG_ERROR(fmt.Sprintf("类型转换错误，需要*model.SubscribeManagerEx 类型，类型为:%T", subscribeTaskInterface))
		return model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.String(), subscribeId, model.OTHER_ERROR))
	}
	subscribeTask := subscribeTaskInterface.(*model.SubscribeLib)
	//更新缓存
	e := FlushOperateTypeCache(subscribeTask, "1", "0")
	if e != nil {
		return model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.String(), subscribeId, model.OTHER_ERROR))
	}

	return model.BuildSingleResponse(model.BuildRespnseObject(ctx.Request.URL.String(), subscribeId, model.OK))
}

func IsExitConfi(keys ...string) (unExsitKeys []string) {
	unExsitKeys = make([]string, 0)
	for _, k := range keys {
		if k == "" {
			unExsitKeys = append(unExsitKeys, k)
		}
	}
	return unExsitKeys
}

func generateSubscribeID() string {
	id_1_12 := constant.GA_ORG_CODE
	id_13_14 := constant.SUBSCRIBE
	id_15_28 := time.Now().Format("20060102150405")
	id_29_33 := fmt.Sprintf("%05v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000))
	return fmt.Sprintf("%s%s%s%s", id_1_12, id_13_14, id_15_28, id_29_33)
}

func generateSubscribeNotificationID() string {
	id_1_12 := constant.GA_ORG_CODE
	id_13_14 := constant.NOTIFICATION
	id_15_28 := time.Now().Format("20060102150405")
	id_29_33 := fmt.Sprintf("%04v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000))
	return fmt.Sprintf("%s%s%s%s", id_1_12, id_13_14, id_15_28, id_29_33)
}
